package com.yyw.gulimall.authserver.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.yyw.common.constant.auth.AuthServerConstant;
import com.yyw.common.constant.common.UrlConstant;
import com.yyw.common.exception.UserRegisterException;
import com.yyw.common.utils.R;
import com.yyw.gulimall.authserver.feign.MemberFeign;
import com.yyw.gulimall.authserver.service.UserService;
import com.yyw.gulimall.authserver.vo.LoginUserVo;
import com.yyw.common.to.oauth.MemberVo;
import com.yyw.gulimall.authserver.vo.RegisterUserVo;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author 易煜玮
 * @ClassName UserServiceImpl.java
 * @Description 用户服务/登录/注册
 * @createTime 2020年12月14日 20:21:00
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class UserServiceImpl implements UserService {

    private final StringRedisTemplate redisTemplate;

    private final MemberFeign memberFeign;

    /**
     * 用户注册
     *
     * @param userVo
     * @param bindingResult
     * @param model
     * @return
     */
    @Override
    public ModelAndView registerUser(RegisterUserVo userVo, BindingResult bindingResult, ModelAndView model) {
        // 1. 添加用户自己输入的值
        model.addObject("userVo", userVo);
        // 2. 检验输入是否正确
        Map<String, Object> map = checkout(userVo, bindingResult, model);
        if (Objects.equals(true, map.get("result"))) {
            // 向会员系统发送请求，注册用户
            R r = memberFeign.save(userVo);
            if (!Objects.equals(r.get("code"), 0)) {
                // 发生异常，如用户名/手机号被注册过
                model.setViewName("register");
                model.addObject("error", r.get("msg"));
                return model;
            }
            model.setViewName("redirect:" + UrlConstant.AUTH_URL + "/login");
            return model;
        } else {
            ModelAndView error = (ModelAndView) map.get("model");
            return error;
        }
    }

    @Override
    public ModelAndView loginUser(LoginUserVo userVo, BindingResult bindingResult, ModelAndView model, HttpSession session) {
        // 1. 保存用户输入的值
        model.addObject("userVo", userVo);
        // 2. 校验输入的值
        if (bindingResult.hasErrors()) {
            Map<String, String> error = bindingResult.getFieldErrors().stream().collect(
                    Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage, (key1, key2) -> key1));
            model.addAllObjects(error);
            model.setViewName("login");
            return model;
        }
        // 3. 调用远程服务，查询用户
        R r = memberFeign.login(userVo);
        if (!Objects.equals(0, r.get("code"))) {
            model.addObject("error", r.get("msg"));
            model.setViewName("login");
            return model;
        }
        // 获取返回的用户信息
        MemberVo data = r.getData("data", new TypeReference<MemberVo>() {
        });
        // 存放session
        session.setAttribute(AuthServerConstant.SESSION_LOGIN_USER, data);
        model.setViewName("redirect:" + UrlConstant.PRODUCT_URL);
        return model;
    }

    /**
     * 校验用户输入的数据是否合法
     *
     * @param userVo
     * @param bindingResult
     * @param model
     * @return
     */
    private Map<String, Object> checkout(RegisterUserVo userVo, BindingResult bindingResult, ModelAndView model) {
        Map<String, String> error = new HashMap<>();
        boolean result = true;
        // 1. 校验输入的值
        if (bindingResult.hasErrors()) {
            error = bindingResult.getFieldErrors().stream().collect(
                    Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage, (key1, key2) -> key1));
            result = false;
        }
        // 2. 验证密码是否一致
        if (!Objects.equals(userVo.getPassword(), userVo.getConfirmPassWord())) {
            error.put("confirmPassWord", "两次输入的密码不一致");
            result = false;
        }
        // 3. 判断验证码
        try {
            if (!Objects.equals(null, userVo.getCode()) && !Objects.equals("", userVo.getCode().trim())) {
                String cacheData = redisTemplate.opsForValue().get(AuthServerConstant.CACHE_PHONE_CODE_PIX + userVo.getMobile());
                if (StringUtils.isEmpty(cacheData)) {
                    throw new UserRegisterException("验证码不存在");
                }
                String code = cacheData.split("_")[0];
                if (!Objects.equals(code, userVo.getCode())) {
                    throw new UserRegisterException("验证码错误");
                }
            } else {
                throw new UserRegisterException("请输入验证码");
            }
        } catch (Exception e) {
            error.put("code", e.getMessage());
            result = false;
        }
        // 4. 判断是否有错误
        if (!result) {
            model.addAllObjects(error);
            model.setViewName("register");
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("result", result);
        resultMap.put("model", model);
        return resultMap;
    }
}
